package io.itit.ecp.admin.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import io.itit.ecp.admin.common.enums.IPhysicalModelModelDataTypeEnums;
import io.itit.ecp.admin.common.enums.IPhysicalModelModelFieldTypeEnums;
import io.itit.ecp.admin.server.entity.DeviceEntity;
import io.itit.ecp.admin.server.entity.DeviceRunningValueEntity;
import io.itit.ecp.admin.server.entity.PhysicalModelEntity;
import io.itit.ecp.admin.server.entity.ProductTypeEntity;
import io.itit.ecp.admin.server.entity.extend.DeviceExtEntity;
import io.itit.ecp.admin.server.entity.extend.PhysicalModelExt;
import io.itit.ecp.admin.server.mapper.DeviceMapper;
import io.itit.ecp.admin.server.service.IDeviceRunningValueService;
import io.itit.ecp.admin.server.service.IDeviceService;
import io.itit.ecp.admin.server.service.IPhysicalModelService;
import io.itit.ecp.admin.server.service.IProductTypeService;
import io.itit.grass.common.server.utils.ConvertUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * @Author：Roy
 * @Description：设备管理服务实现类
 * @Date：Create by 2023-11-30 18:51:39
 */
@Service
public class DeviceServiceImpl extends JoinServiceImpl<DeviceMapper, DeviceEntity> implements IDeviceService {

    @Resource
    private IProductTypeService productTypeService;

    @Resource
    private IPhysicalModelService physicalModelService;

    @Resource
    private IDeviceRunningValueService deviceRunningValueService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveDeviceBatch(List<DeviceEntity> entities) {
        return this.saveBatch(entities);
    }

    @Override
    public List<DeviceExtEntity> countProductType() {
        return this.baseMapper.countProductType();
    }

    @Override
    public int countOnline(String sceneProjectId, String sceneEdificeId, String sceneFloorId) {
        return this.baseMapper.selectCount(new LambdaQueryWrapper<DeviceEntity>()
                .eq(StringUtils.hasLength(sceneProjectId), DeviceEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), DeviceEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), DeviceEntity::getSceneFloorId, sceneFloorId)
                .eq(DeviceEntity::getDeviceStatus, "1")).intValue();
    }

    @Override
    public DeviceEntity getByDeviceCode(String deviceCode) {
        return lambdaQuery()
                .eq(DeviceEntity::getDeviceCode, deviceCode).one();
    }

    @Override
    public int countOffline(String sceneProjectId, String sceneEdificeId, String sceneFloorId) {
        return this.baseMapper.selectCount(new LambdaQueryWrapper<DeviceEntity>()
                .eq(StringUtils.hasLength(sceneProjectId), DeviceEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), DeviceEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), DeviceEntity::getSceneFloorId, sceneFloorId)
                .eq(DeviceEntity::getDeviceStatus, "2")).intValue();
    }

    @Override
    public List<PhysicalModelExt> queryModelByDeviceId(String id) {
        DeviceEntity deviceEntity = getById(id);
        if (Objects.isNull(deviceEntity)) {
            return Collections.emptyList();
        }
        ProductTypeEntity productTypeEntity = productTypeService.getById(deviceEntity.getProductTypeId());
        if (Objects.isNull(productTypeEntity)) {
            return Collections.emptyList();
        }
        String modelIds = productTypeEntity.getModelIds();
        String[] modelIdsArray = null;
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(modelIds)) {
            modelIdsArray = modelIds.split(",");
        }
        if (Objects.isNull(modelIdsArray) || ArrayUtils.isEmpty(modelIdsArray)) {
            return Collections.emptyList();
        }
        List<PhysicalModelEntity> list = physicalModelService.listByIds(Arrays.asList(modelIdsArray));
        Map<String, DeviceRunningValueEntity> physicalModelIdMap = deviceRunningValueService.findByDeviceId(deviceEntity.getId())
                .stream()
                .collect(Collectors.toMap(DeviceRunningValueEntity::getPhysicalModelId, Function.identity()));
        List<PhysicalModelExt> respList = ConvertUtils.convert(list, PhysicalModelExt.class);
        for (PhysicalModelExt item : respList) {
            DeviceRunningValueEntity runningValueEntity = physicalModelIdMap.get(item.getId());
            if (Objects.nonNull(runningValueEntity) && Objects.nonNull(runningValueEntity.getRunningValue())) {
                Object newValue = null;
                String fieldType = item.getFieldType();
                if (IPhysicalModelModelFieldTypeEnums.INTEGER.getValue().equals(fieldType)) {
                    newValue = Integer.parseInt(runningValueEntity.getRunningValue());
                } else if (IPhysicalModelModelFieldTypeEnums.DECIMAL.getValue().equals(fieldType)) {
                    newValue = Double.parseDouble(runningValueEntity.getRunningValue());
                } else if (IPhysicalModelModelFieldTypeEnums.BOOL.getValue().equals(fieldType) ||
                        IPhysicalModelModelFieldTypeEnums.ENUMS.getValue().equals(fieldType) ||
                        IPhysicalModelModelFieldTypeEnums.STR.getValue().equals(fieldType)) {
                    newValue = runningValueEntity.getRunningValue();
                } else if (IPhysicalModelModelFieldTypeEnums.ARRAY.getValue().equals(fieldType)) {
                    newValue = runningValueEntity.getRunningValue().split(",");
                } else if (IPhysicalModelModelFieldTypeEnums.OBJECTS.getValue().equals(fieldType)) {
                    newValue = JSON.parse(runningValueEntity.getRunningValue());
                }
                item.setNewValue(newValue);
            }
            Map<String, Object> dataExtMap = item.getDataExtMap();
            if (Objects.nonNull(dataExtMap) && IPhysicalModelModelDataTypeEnums.FIXED.getValue().equals(String.valueOf(dataExtMap.get("dataType")))
                    && Objects.nonNull(dataExtMap.get("fixedValue"))) {
                item.setNewValue(dataExtMap.get("fixedValue"));
            }
        }
        return respList;
    }
}